package cn.vehicle.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.ArrayList;
import java.util.List;

/**
 * 控制器方法拦截切面，用于日志打印和参数/返回值格式化
 */
@Aspect
@Component
@Slf4j
public class ControllerAspect {

    private static final Logger logger = LoggerFactory.getLogger(ControllerAspect.class);
    private final ObjectMapper objectMapper = new ObjectMapper();

    // 需要排除的参数类型（可根据实际需求扩展）
    private static final List<Class<?>> EXCLUDED_TYPES = new ArrayList<>();

    static {
        // 初始化需要排除的类型，例如ServletRequest、ServletResponse等
        try {
            EXCLUDED_TYPES.add(Class.forName("javax.servlet.ServletRequest"));
            EXCLUDED_TYPES.add(Class.forName("javax.servlet.ServletResponse"));
            EXCLUDED_TYPES.add(Class.forName("javax.servlet.http.HttpSession"));
        } catch (ClassNotFoundException e) {
            logger.warn("初始化排除类型失败", e);
        }
    }

    /**
     * 定义切点：拦截cn.car.controller包下的所有public方法
     */
    @Pointcut("execution(public * cn.vehicle.controller..*(..))")
    public void controllerPointcut() {
    }

    /**
     * 环绕通知：处理参数格式化和返回结果格式化
     */
    @Around("controllerPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    //    // 打印请求信息和格式化后的参数
    //    logger.info("===== 开始执行方法：{} =====", joinPoint.getSignature().toShortString());
    //    String paramsJson = formatParams(joinPoint.getArgs());
    //    logger.info("方法参数：{}", paramsJson);
    //
    //    // 执行目标方法
    //    Object result = joinPoint.proceed();
    //
    //    // 打印格式化后的返回结果
    //    String resultJson = formatResult(result);
    //    logger.info("返回结果：{}", resultJson);
    //    logger.info("===== 方法执行结束：{} =====", joinPoint.getSignature().toShortString());
    //
    //    return result;
    //}
    //
    ///**
    // * 格式化参数为JSON字符串（排除指定类型）
    // * @param args 方法参数数组
    // * @return 格式化后的JSON字符串
    // */
    //private String formatParams(Object[] args) {
    //    if (args == null || args.length == 0) {
    //        return "[]";
    //    }
    //
    //    // 过滤掉需要排除的参数类型
    //    List<Object> validParams = new ArrayList<>();
    //    for (Object arg : args) {
    //        if (arg != null && !isExcludedType(arg.getClass())) {
    //            validParams.add(arg);
    //        }
    //    }
    //
    //    try {
    //        return objectMapper.writeValueAsString(validParams);
    //    } catch (JsonProcessingException e) {
    //        logger.error("参数JSON格式化失败", e);
    //        return "参数格式化失败：" + e.getMessage();
    //    }

        long startTime = System.currentTimeMillis();

        // 获取请求信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = null;
        if (attributes != null) {
            request = attributes.getRequest();
        }

        // 获取方法信息
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();

        // 记录请求开始信息

        if (request != null) {
            log.info("=== Controller请求开始 ===");
            log.info("请求URL: {} {}", request.getMethod(), request.getRequestURI());
            log.info("执行方法: {}.{}", className, methodName);
            log.info("方法参数: {}", formatResult(args));
        }



        Object result;
        try {
            // 执行目标方法
            result = joinPoint.proceed();

            // 计算执行时间
            long executionTime = System.currentTimeMillis() - startTime;

            if (result != null) {
                // 记录响应信息
                log.info("方法返回: {}", formatResult(result));
                log.info("执行耗时: {}ms", executionTime);
                log.info("=== Controller请求结束 ===");
            }



            return result;

        } catch (Exception e) {
            long executionTime = System.currentTimeMillis() - startTime;
            log.error("方法执行异常: {}", e.getMessage());
            log.error("执行耗时: {}ms", executionTime);
            log.error("=== Controller请求异常结束 ===\n");
            throw e;
        }
    }

    /**
     * 格式化返回结果为JSON字符串
     * @param result 方法返回结果
     * @return 格式化后的JSON字符串
     */
    private String formatResult(Object result) {
        if (result == null) {
            return "null";
        }

        try {
            return objectMapper.writeValueAsString(result);
        } catch (JsonProcessingException e) {
            logger.error("返回结果JSON格式化失败", e);
            return "返回结果格式化失败：" + e.getMessage();
        }
    }

    /**
     * 判断是否为需要排除的参数类型（包括父类类型判断）
     * @param clazz 参数类型
     * @return 是否需要排除
     */
    private boolean isExcludedType(Class<?> clazz) {
        for (Class<?> excludedType : EXCLUDED_TYPES) {
            if (excludedType.isAssignableFrom(clazz)) {
                return true;
            }
        }
        return false;
    }
}